/*
 * @Author: 杜颖 3263107847@qq.com
 * @Date: 2025-06-27 10:17:10
 * @LastEditors: 杜颖 3263107847@qq.com
 * @LastEditTime: 2025-06-28 17:38:58
 * @FilePath: \biji\Calculator.java
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import javax.sound.sampled.*;

// 增强版计算器，实现了各种扩展功能
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.script.*;
import java.awt.*;
import java.awt.event.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

// 高级科学计算器类，继承JFrame实现图形界面，实现ActionListener处理按钮点击事件
public class EnhancedCalculator extends JFrame implements ActionListener {
    // 界面组件变量
    private JPanel north, center;             // 顶部和中间面板
    private JTextField field;                // 输入显示文本框
    private JButton[] btns;                  // 按钮数组
    private JLabel statusLabel;              // 底部状态栏
    
    // 音效相关变量
    private Clip buttonSound;                // 基础按键音效
    private Clip[] numberSounds;             // 数字键差异化音效
    private boolean isResultDisplayed = false; // 标记是否显示了计算结果
    private boolean isScientificMode = false; // 科学计算模式标志
    
    // 音效配置常量
    private static final int NOTE_COUNT = 7;  // 7个基础音符
    private static final float SAMPLE_RATE = 44100.0f; // 采样率
    private float volume = 0.8f;             // 音量控制
    private float pitchFactor = 1.0f;        // 音调因子

    // 构造方法，初始化计算器界面
    public EnhancedCalculator() {
        setTitle("高级科学计算器");              // 设置窗口标题
        setSize(800, 700);                    // 设置窗口大小
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置关闭操作
        setLocationRelativeTo(null);           // 窗口居中显示
        initComponent();                       // 初始化界面组件
        createButtonSounds();                  // 生成按钮音效
        setVisible(true);                      // 显示窗口
    }

    // 初始化界面组件
    private void initComponent() {
        // 设置窗口内容面板并添加渐变背景
        setContentPane(new JPanel(new BorderLayout()) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                // 创建从浅蓝色到深蓝色的渐变背景
                Graphics2D g2d = (Graphics2D) g;
                Color color1 = new Color(240, 240, 255);
                Color color2 = new Color(200, 220, 255);
                GradientPaint gp = new GradientPaint(0, 0, color1, 0, getHeight(), color2);
                g2d.setPaint(gp);
                g2d.fillRect(0, 0, getWidth(), getHeight());
            }
        });

        north = new JPanel(new BorderLayout());  // 初始化顶部面板
        north.setOpaque(false);                  // 使面板透明以显示背景
        center = new JPanel(new GridLayout(6, 5, 5, 5)); // 6行5列网格布局，间距5
        center.setOpaque(false);                 // 使面板透明
        
        // 初始化输入显示文本框
        field = new JTextField();
        field.setPreferredSize(new Dimension(800, 150)); // 设置首选大小
        field.setEditable(false);                        // 文本框不可编辑
        field.setFont(new Font("SansSerif", Font.BOLD, 35)); // 设置字体
        field.setHorizontalAlignment(JTextField.RIGHT);    // 文本右对齐
        field.setBackground(new Color(245, 245, 255));     // 设置背景色
        // 设置边框：2像素黑色实线边框，内部边距10像素
        field.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(Color.BLACK, 2),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)
        ));

        // 定义按钮文本数组，包括数字、运算符和科学计算功能
        String[] str = new String[] {
            "7", "8", "9", "÷", "√",
            "4", "5", "6", "×", "x!",
            "1", "2", "3", "-", "ln",
            "0", ".", "=", "+", "log",
            "C", "B", "±", "sin", "cos",
            "T", "S", "π", "e", "MODE"
        };

        btns = new JButton[str.length]; // 初始化按钮数组
        for (int i = 0; i < btns.length; i++) {
            btns[i] = new JButton(str[i]); // 创建按钮并设置文本
            btns[i].setFont(new Font("SansSerif", Font.BOLD, 20)); // 设置字体
            btns[i].setFocusPainted(false); // 不绘制焦点边框
            
            // 根据按钮类型设置不同背景色
            if (str[i].equals("MODE")) { // 模式切换按钮
                btns[i].setBackground(new Color(255, 250, 150));
            } else if (i % 5 == 3 || i % 5 == 4) { // 运算符和科学功能按钮
                btns[i].setBackground(new Color(200, 220, 255));
            } else { // 数字按钮
                btns[i].setBackground(new Color(240, 240, 240));
            }
            
            btns[i].setForeground(Color.BLACK); // 设置前景色为黑色
            btns[i].setBorder(BorderFactory.createRaisedBevelBorder()); // 设置凸起边框
            
            // 添加鼠标事件监听器，实现按钮悬停和点击效果
            btns[i].addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    // 鼠标进入时按钮背景变亮
                    ((JButton)e.getSource()).setBackground(((JButton)e.getSource()).getBackground().brighter());
                }
                
                @Override
                public void mouseExited(MouseEvent e) {
                    JButton btn = (JButton)e.getSource();
                    String text = btn.getText();
                    // 鼠标离开时恢复按钮背景色
                    if (text.equals("MODE")) {
                        btn.setBackground(new Color(255, 250, 150));
                    } else if (text.equals("÷") || text.equals("×") || text.equals("-") || text.equals("+") ||
                              text.equals("√") || text.equals("x!") || text.equals("ln") || text.equals("log") ||
                              text.equals("sin") || text.equals("cos") || text.equals("±") || text.equals("π") || text.equals("e")) {
                        btn.setBackground(new Color(200, 220, 255));
                    } else {
                        btn.setBackground(new Color(240, 240, 240));
                    }
                }
                
                @Override
                public void mousePressed(MouseEvent e) {
                    // 鼠标按下时设置凹陷边框
                    ((JButton)e.getSource()).setBorder(BorderFactory.createLoweredBevelBorder());
                }
                
                @Override
                public void mouseReleased(MouseEvent e) {
                    // 鼠标释放时恢复凸起边框
                    ((JButton)e.getSource()).setBorder(BorderFactory.createRaisedBevelBorder());
                }
            });
        }

        north.add(field, BorderLayout.CENTER); // 将文本框添加到顶部面板中心
        
        // 将所有按钮添加到中间面板
        for (JButton btn : btns) {
            center.add(btn);
        }

        // 将面板添加到窗口的对应区域
        add(north, BorderLayout.NORTH);
        add(center, BorderLayout.CENTER);
        
        // 初始化底部状态栏
        statusLabel = new JLabel("就绪 - 标准模式", JLabel.CENTER);
        statusLabel.setFont(new Font("SansSerif", Font.PLAIN, 14));
        statusLabel.setOpaque(true);
        statusLabel.setBackground(new Color(220, 230, 240));
        add(statusLabel, BorderLayout.SOUTH);

        // 为所有按钮添加动作监听器
        for (JButton btn : btns) {
            btn.addActionListener(this);
        }
        
        // 初始化菜单条
        initMenuBar();
    }

    // 初始化菜单条
    private void initMenuBar() {
        JMenuBar menuBar = new JMenuBar(); // 创建菜单条
        JMenu optionsMenu = new JMenu("选项"); // 创建选项菜单
        
        JMenuItem soundSettings = new JMenuItem("音效设置"); // 创建音效设置菜单项
        soundSettings.addActionListener(e -> showSoundSettings()); // 添加动作监听器
        
        // 创建启用/禁用音效的复选框菜单项，默认为启用
        JCheckBoxMenuItem soundToggle = new JCheckBoxMenuItem("启用音效", true);
        soundToggle.addActionListener(e -> {
            boolean soundEnabled = soundToggle.isSelected();
            // 更新状态栏显示
            statusLabel.setText(soundEnabled ? "音效已开启 - 标准模式" : "音效已关闭 - 标准模式");
        });
        
        // 将菜单项添加到选项菜单
        optionsMenu.add(soundToggle);
        optionsMenu.add(soundSettings);
        menuBar.add(optionsMenu); // 将选项菜单添加到菜单条
        setJMenuBar(menuBar);     // 设置窗口的菜单条
    }

    // 显示音效设置对话框
    private void showSoundSettings() {
        JDialog settingsDialog = new JDialog(this, "音效设置", true); // 创建模态对话框
        settingsDialog.setSize(300, 200);                            // 设置对话框大小
        settingsDialog.setLocationRelativeTo(this);                 // 对话框相对于计算器窗口居中
        
        JPanel panel = new JPanel(new GridLayout(3, 2)); // 创建3行2列的面板
        
        // 创建音量滑块，范围0-100，初始值为当前音量的100倍
        JSlider volumeSlider = new JSlider(0, 100, (int)(volume * 100));
        // 创建音调滑块，范围50-150，初始值为当前音调因子的100倍
        JSlider pitchSlider = new JSlider(50, 150, (int)(pitchFactor * 100));
        
        // 音量滑块值变化时更新音量
        volumeSlider.addChangeListener(e -> volume = volumeSlider.getValue() / 100.0f);
        // 音调滑块值变化时更新音调因子
        pitchSlider.addChangeListener(e -> pitchFactor = pitchSlider.getValue() / 100.0f);
        
        // 将标签和滑块添加到面板
        panel.add(new JLabel("音量:"));
        panel.add(volumeSlider);
        panel.add(new JLabel("音调:"));
        panel.add(pitchSlider);
        
        // 创建应用按钮
        JButton applyButton = new JButton("应用");
        applyButton.addActionListener(e -> settingsDialog.dispose()); // 点击应用后关闭对话框
        
        panel.add(new JLabel());
        panel.add(applyButton);
        settingsDialog.add(panel); // 将面板添加到对话框
        settingsDialog.setVisible(true); // 显示对话框
    }

    // 生成按钮音效
    private void createButtonSounds() {
        try {
            // 创建基础按键音效（功能键/运算符），A4音(440Hz)，持续150毫秒
            buttonSound = createTone(440, 150);
            statusLabel.setText("音效生成成功：基础按键音 - 标准模式");
            
            // 创建数字键差异化音效（C4到B4音阶）
            numberSounds = new Clip[NOTE_COUNT];
            for (int i = 0; i < NOTE_COUNT; i++) {
                // 计算音阶频率（十二平均律）
                float frequency = 261.63f * (float) Math.pow(2, (i) / 12.0);
                numberSounds[i] = createTone(frequency, 120); // 持续120毫秒
            }
        } catch (Exception e) {
            statusLabel.setText("音效生成失败：" + e.getMessage()); // 显示错误信息
            e.printStackTrace();
        }
    }
    
    // 生成指定频率和持续时间的音效
    private Clip createTone(float frequency, int durationMs) throws LineUnavailableException {
        try {
            // 应用用户设置的音调因子
            frequency *= pitchFactor;
            
            // 音频格式设置：44100Hz采样率，16位，单声道
            int sampleSizeInBits = 16;
            int channels = 1;
            boolean signed = true;
            boolean bigEndian = false;
            
            AudioFormat format = new AudioFormat(
                SAMPLE_RATE, sampleSizeInBits, channels, signed, bigEndian
            );
            
            ByteArrayOutputStream out = new ByteArrayOutputStream(); // 用于存储音频数据
            // 计算样本数量
            int numSamples = (int) (SAMPLE_RATE * durationMs / 1000.0);
            byte[] samples = new byte[numSamples * 2]; // 16位音频，每个样本2字节
            
            // 生成正弦波音频数据
            for (int i = 0; i < numSamples; i++) {
                double angle = 2.0 * Math.PI * i / (SAMPLE_RATE / frequency);
                // 计算样本值并应用音量
                short sample = (short) (32767.0 * Math.sin(angle) * volume);
                samples[2 * i] = (byte) (sample & 0xFF);         // 低字节
                samples[2 * i + 1] = (byte) (sample >> 8);       // 高字节
            }
            
            // 添加包络线使音效更自然
            samples = applyEnvelope(samples, durationMs);
            // 添加谐波丰富音色
            samples = addHarmonics(samples, frequency);
            
            out.write(samples, 0, samples.length); // 将样本写入输出流
            byte[] audioBytes = out.toByteArray(); // 转换为字节数组
            ByteArrayInputStream in = new ByteArrayInputStream(audioBytes); // 创建输入流
            
            // 创建音频输入流
            AudioInputStream audioInputStream = new AudioInputStream(
                in, format, audioBytes.length / format.getFrameSize()
            );
            
            // 打开并返回音频剪辑
            Clip clip = AudioSystem.getClip();
            clip.open(audioInputStream);
            return clip;
        } catch (IOException e) {
            throw new LineUnavailableException(e.getMessage());
        }
    }
    
    // 应用包络线到音频样本（起音-衰减-持续-释音）
    private byte[] applyEnvelope(byte[] samples, int durationMs) {
        int numSamples = samples.length / 2; // 16位样本数
        float attackTime = 0.05f;  // 起音时间0.05秒
        float decayTime = 0.03f;   // 衰减时间0.03秒
        float sustainLevel = 0.7f; // 持续音量
        float releaseTime = 0.05f; // 释音时间0.05秒
        
        // 计算各阶段的样本数
        int attackSamples = (int) (SAMPLE_RATE * attackTime);
        int decaySamples = (int) (SAMPLE_RATE * decayTime);
        int releaseSamples = (int) (SAMPLE_RATE * releaseTime);
        int sustainSamples = Math.max(0, numSamples - attackSamples - decaySamples - releaseSamples);
        
        // 为每个样本应用包络
        for (int i = 0; i < numSamples; i++) {
            float amplitude = 1.0f;
            if (i < attackSamples) {
                // 起音阶段：线性上升
                amplitude = (float) i / attackSamples;
            } else if (i < attackSamples + decaySamples) {
                // 衰减阶段：指数下降到持续音量
                float decayProgress = (float) (i - attackSamples) / decaySamples;
                amplitude = 1.0f - (1.0f - sustainLevel) * decayProgress;
            } else if (i > numSamples - releaseSamples) {
                // 释音阶段：指数下降到0
                float releaseProgress = (float) (numSamples - i) / releaseSamples;
                amplitude = sustainLevel * releaseProgress;
            } else {
                // 持续阶段
                amplitude = sustainLevel;
            }
            
            // 应用包络到样本
            int sampleIndex = i * 2;
            short sample = (short) ((samples[sampleIndex] & 0xFF) | (samples[sampleIndex + 1] << 8));
            sample = (short) (sample * amplitude);
            samples[sampleIndex] = (byte) (sample & 0xFF);
            samples[sampleIndex + 1] = (byte) (sample >> 8);
        }
        
        return samples;
    }
    
    // 添加谐波到音频样本以丰富音色
    private byte[] addHarmonics(byte[] samples, float frequency) {
        int numSamples = samples.length / 2;
        
        // 添加二次谐波（高八度）和三次谐波（高十二度）
        float harmonic1Freq = frequency * 2.0f;
        float harmonic2Freq = frequency * 3.0f;
        
        // 生成包含主音和谐波的样本
        for (int i = 0; i < numSamples; i++) {
            double angle = 2.0 * Math.PI * i / (SAMPLE_RATE / frequency);
            double harmonic1Angle = 2.0 * Math.PI * i / (SAMPLE_RATE / harmonic1Freq);
            double harmonic2Angle = 2.0 * Math.PI * i / (SAMPLE_RATE / harmonic2Freq);
            
            // 主音 + 谐波（权重递减）
            short sample = (short) (
                32767.0 * Math.sin(angle) +
                32767.0 * 0.3 * Math.sin(harmonic1Angle) +
                32767.0 * 0.1 * Math.sin(harmonic2Angle)
            );
            
            int sampleIndex = i * 2;
            samples[sampleIndex] = (byte) (sample & 0xFF);
            samples[sampleIndex + 1] = (byte) (sample >> 8);
        }
        
        return samples;
    }

    // 播放按钮音效
    private void playButtonSound(String buttonType) {
        // 检查音效是否启用
        JCheckBoxMenuItem soundToggle = (JCheckBoxMenuItem)((JMenuBar)getJMenuBar()).getMenu(0).getItem(0);
        if (!soundToggle.isSelected() || buttonType == null) return;
        
        try {
            Clip clip;
            float btnVolume = volume;
            
            // 根据按钮类型选择不同的音效
            switch (buttonType) {
                case "NUMBER": // 数字键
                    int noteIndex = getNoteIndexForNumber(btns.length);
                    clip = numberSounds[noteIndex >= 0 && numberSounds[noteIndex] != null ? noteIndex : 0];
                    btnVolume = volume * 0.9f; // 数字键音量稍低
                    break;
                case "SCIENTIFIC": // 科学计算按钮
                    clip = createTone(493.88f, 130); // B4音
                    btnVolume = volume * 1.0f; // 正常音量
                    break;
                case "OPERATOR": // 运算符
                    clip = buttonSound;
                    btnVolume = volume * 0.85f; // 运算符音量
                    break;
                case "FUNCTION": // 功能键（如C、MODE）
                    clip = buttonSound;
                    btnVolume = volume * 0.95f; // 功能键音量稍高
                    break;
                default:
                    return;
            }
            
            // 设置音量
            if (clip != null && clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
                FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                float dB = (float) (Math.log(btnVolume) / Math.log(10.0) * 20.0);
                gainControl.setValue(dB);
            }
            
            playClip(clip); // 播放音效
        } catch (Exception e) {
            statusLabel.setText("音效播放错误：" + e.getMessage()); // 显示错误信息
        }
    }
    
    // 播放音效片段的通用方法，在新线程中播放避免阻塞UI
    private void playClip(Clip clip) {
        if (clip == null) return;
        
        new Thread(() -> {
            if (clip.isRunning()) {
                clip.stop(); // 停止当前播放
            }
            clip.setFramePosition(0); // 重置播放位置
            clip.start(); // 开始播放
        }).start();
    }
    
    // 根据数字键索引获取音符索引，用于数字键差异化音效
    private int getNoteIndexForNumber(int buttonIndex) {
        int numberIndex = buttonIndex % 16; // 16个数字相关键
        return numberIndex % NOTE_COUNT;    // 映射到7个音符
    }

    // 设置按钮文本并执行相应操作
    private void setBtnText(String text) {
        // 根据按钮类型播放不同音效
        String buttonType = getButtonType(text);
        playButtonSound(buttonType);
        
        // 如果已显示结果且点击数字键（非正负号），清空当前显示
        if (isResultDisplayed && Character.isDigit(text.charAt(0)) && !text.equals("±")) {
            field.setText("");
            isResultDisplayed = false;
        }

        // 根据按钮文本执行不同操作
        switch (text) {
            case "C": // 清空按钮
                field.setText("");
                statusLabel.setText("已清空");
                break;
            case "B": // 退格按钮
                String numText = field.getText();
                if (!numText.isEmpty()) {
                    field.setText(numText.substring(0, numText.length() - 1));
                    statusLabel.setText("已删除最后一个字符");
                }
                break;
            case "T": // 显示时间按钮
                showTime();
                break;
            case "S": // 显示音效面板按钮
                showSoundPanel();
                break;
            case "MODE": // 模式切换按钮
                toggleScientificMode();
                break;
            case "=": // 等号按钮，执行计算
                calculate();
                break;
            case "±": // 正负号切换按钮
                applySignChange();
                break;
            case "π": // 插入圆周率
                field.setText(String.valueOf(Math.PI));
                statusLabel.setText("插入圆周率");
                break;
            case "e": // 插入自然常数
                field.setText(String.valueOf(Math.E));
                statusLabel.setText("插入自然常数");
                break;
            case "√": // 开根号
                applySquareRoot();
                break;
            case "x!": // 阶乘
                applyFactorial();
                break;
            case "ln": // 自然对数
                applyNaturalLog();
                break;
            case "log": // 以10为底的对数
                applyLog10();
                break;
            case "sin": // 正弦函数
                applySine();
                break;
            case "cos": // 余弦函数
                applyCosine();
                break;
            default:
                // 验证输入有效性并添加到显示框
                if (isValidInput(text)) {
                    String oldText = field.getText();
                    field.setText(oldText + text);
                }
                break;
        }
    }
    
    // 切换科学计算模式
    private void toggleScientificMode() {
        isScientificMode = !isScientificMode; // 切换模式标志
        // 更新状态栏显示
        statusLabel.setText(isScientificMode ? "就绪 - 科学模式" : "就绪 - 标准模式");
    }
    
    // 应用正负号切换
    private void applySignChange() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析当前数字
            field.setText(String.valueOf(-num));    // 显示负数
            statusLabel.setText("切换符号");
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("无法切换符号");
        }
    }
    
    // 应用开根号计算
    private void applySquareRoot() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析数字
            if (num < 0) {
                field.setText("错误：不能对负数开根号"); // 处理负数
                statusLabel.setText("开根号错误");
                return;
            }
            double result = Math.sqrt(num); // 计算平方根
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算开根号");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("开根号错误");
        }
    }
    
    // 应用阶乘计算
    private void applyFactorial() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            int num = Integer.parseInt(text); // 解析整数
            if (num < 0) {
                field.setText("错误：不能计算负数的阶乘"); // 处理负数
                statusLabel.setText("阶乘错误");
                return;
            }
            double result = factorial(num); // 计算阶乘
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算阶乘");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("阶乘错误");
        } catch (StackOverflowError soe) {
            field.setText("数值过大"); // 处理大数溢出
            statusLabel.setText("阶乘计算溢出");
        }
    }
    
    // 递归计算阶乘
    private double factorial(int n) {
        if (n == 0 || n == 1) return 1; // 递归基例
        return n * factorial(n - 1);    // 递归计算
    }
    
    // 应用自然对数(ln)计算
    private void applyNaturalLog() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析数字
            if (num <= 0) {
                field.setText("错误：对数参数必须大于0"); // 处理非正数
                statusLabel.setText("自然对数错误");
                return;
            }
            double result = Math.log(num); // 计算自然对数
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算自然对数");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("自然对数错误");
        }
    }
    
    // 应用以10为底的对数(log)计算
    private void applyLog10() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析数字
            if (num <= 0) {
                field.setText("错误：对数参数必须大于0"); // 处理非正数
                statusLabel.setText("对数错误");
                return;
            }
            double result = Math.log10(num); // 计算以10为底的对数
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算对数");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("对数错误");
        }
    }
    
    // 应用正弦函数计算
    private void applySine() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析数字
            // 将角度转换为弧度
            double radians = Math.toRadians(num);
            double result = Math.sin(radians); // 计算正弦值
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算正弦值");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("正弦计算错误");
        }
    }
    
    // 应用余弦函数计算
    private void applyCosine() {
        String text = field.getText();
        if (text.isEmpty()) return;
        
        try {
            double num = Double.parseDouble(text); // 解析数字
            // 将角度转换为弧度
            double radians = Math.toRadians(num);
            double result = Math.cos(radians); // 计算余弦值
            field.setText(formatResult(result)); // 格式化显示结果
            statusLabel.setText("计算余弦值");
            isResultDisplayed = true;
        } catch (NumberFormatException e) {
            field.setText("格式错误"); // 处理非数字输入
            statusLabel.setText("余弦计算错误");
        }
    }
    
    // 格式化计算结果，去除末尾无意义的零和小数点
    private String formatResult(double result) {
        if (result == (long) result) {
            return String.format("%d", (long) result); // 整数格式
        }
        return String.format("%.10f", result).replaceAll("0+$", "").replaceAll("\\.$", "");
    }
    
    // 判断按钮类型（数字/运算符/科学计算/功能键）
    private String getButtonType(String text) {
        if (text.matches("[0-9]")) {
            return "NUMBER"; // 数字键
        } else if (text.equals("+") || text.equals("-") || text.equals("×") || text.equals("÷")) {
            return "OPERATOR"; // 运算符
        } else if (text.equals("√") || text.equals("x!") || text.equals("ln") || text.equals("log") || 
                   text.equals("sin") || text.equals("cos") || text.equals("±")) {
            return "SCIENTIFIC"; // 科学计算功能
        } else if (text.equals("C") || text.equals("B") || text.equals("T") || text.equals("S") || 
                   text.equals("=") || text.equals("MODE") || text.equals("π") || text.equals("e")) {
            return "FUNCTION"; // 功能键
        }
        return null;
    }

    // 验证输入是否有效
    private boolean isValidInput(String input) {
        String currentText = field.getText();
        
        if (currentText.isEmpty()) {
            // 空输入框只能输入数字、小数点或正负号
            return Character.isDigit(input.charAt(0)) || input.equals(".") || input.equals("±");
        }
        
        char lastChar = currentText.charAt(currentText.length() - 1);
        
        if (input.equals(".")) {
            // 小数点处理：不能连续输入小数点，且当前数字段不能已有小数点
            if (lastChar == '.') return false;
            
            List<String> operators = Arrays.asList("+", "-", "×", "÷");
            int lastOpIndex = -1;
            
            for (String op : operators) {
                int index = currentText.lastIndexOf(op);
                if (index > lastOpIndex) {
                    lastOpIndex = index;
                }
            }
            
            String currentNumber = lastOpIndex >= 0 ? 
                currentText.substring(lastOpIndex + 1) : currentText;
            
            return !currentNumber.contains(".");
        }
        
        if (isOperator(input)) {
            // 操作符处理：不能连续输入操作符或函数，不能紧跟小数点
            if (isOperator(String.valueOf(lastChar)) || lastChar == '√' || lastChar == 'x' ||
                lastChar == 'l' || lastChar == 's' || lastChar == 'c') {
                return false;
            }
            if (lastChar == '.') return false;
        }
        
        return true;
    }

    // 判断是否为运算符
    private boolean isOperator(String s) {
        return s.equals("+") || s.equals("-") || s.equals("×") || s.equals("÷");
    }

    // 显示当前时间
    private void showTime() {
        LocalDateTime now = LocalDateTime.now(); // 获取当前时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 定义时间格式
        field.setText(now.format(formatter)); // 显示时间
        statusLabel.setText("显示当前时间");
        isResultDisplayed = true;
    }

    // 显示简易钢琴面板
    private void showSoundPanel() {
        // 创建钢琴窗口
        JFrame pianoFrame = new JFrame("简易钢琴");
        pianoFrame.setSize(600, 200);
        pianoFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        pianoFrame.setLocationRelativeTo(this);
        
        JPanel pianoPanel = new JPanel(new GridLayout(1, 7)); // 创建7个琴键的面板
        
        String[] notes = {"C", "D", "E", "F", "G", "A", "B"}; // 音符名称
        for (String note : notes) {
            JButton key = new JButton(note); // 创建琴键按钮
            key.setBackground(Color.WHITE);  // 设置白色背景
            key.setForeground(Color.BLACK);  // 设置黑色前景
            key.setBorder(BorderFactory.createLineBorder(Color.BLACK)); // 设置黑色边框
            key.setFont(new Font("SansSerif", Font.BOLD, 16)); // 设置字体
            
            // 琴键点击事件处理
            key.addActionListener(e -> {
                statusLabel.setText("弹奏音符: " + note); // 更新状态栏
                try {
                    // 计算音符频率并生成音效
                    float frequency = 261.63f * (float) Math.pow(2, Arrays.asList(notes).indexOf(note) / 12.0);
                    Clip noteClip = createTone(frequency, 300);
                    playClip(noteClip);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
            
            pianoPanel.add(key); // 将琴键添加到面板
        }
        
        pianoFrame.add(pianoPanel); // 将面板添加到窗口
        pianoFrame.setVisible(true); // 显示窗口
    }

    // 执行表达式计算
    private void calculate() {
        String expression = field.getText(); // 获取输入表达式
        // 替换乘除符号为JavaScript可识别的符号
        expression = expression.replace("×", "*").replace("÷", "/");
        
        // 处理阶乘表达式
        expression = expression.replace("x!", "factorial(");
        if (expression.contains("factorial(")) {
            // 查找阶乘表达式并计算
            int start = expression.indexOf("factorial(") + 9;
            int end = expression.indexOf(")", start);
            if (start > 8 && end > start) {
                String numStr = expression.substring(start, end);
                try {
                    int num = Integer.parseInt(numStr);
                    double result = factorial(num);
                    expression = expression.substring(0, start - 9) + result + expression.substring(end + 1);
                } catch (Exception e) {
                    field.setText("阶乘计算错误");
                    statusLabel.setText("表达式错误");
                    return;
                }
            }
        }

        // 使用JavaScript引擎计算表达式
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        
        try {
            // 注册阶乘函数到JavaScript引擎
            engine.eval("function factorial(n) { if(n==0||n==1)return 1; else return n*factorial(n-1); }");
            Object result = engine.eval(expression); // 计算表达式
            field.setText(formatResult(Double.parseDouble(result.toString()))); // 显示结果
            statusLabel.setText("计算完成");
            isResultDisplayed = true;
        } catch (ScriptException e) {
            field.setText("运算错误"); // 处理计算错误
            statusLabel.setText("表达式错误");
            e.printStackTrace();
        } catch (NumberFormatException nfe) {
            field.setText("结果格式错误"); // 处理结果格式错误
            statusLabel.setText("计算结果异常");
        }
    }

    // 处理按钮点击事件
    @Override
    public void actionPerformed(ActionEvent a) {
        Object source = a.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton) source;
            String text = btn.getText();
            
            // 自动补零处理：当点击小数点且输入框为空时，自动添加0
            if (text.equals(".") && field.getText().isEmpty()) {
                field.setText("0");
            }
            
            setBtnText(text); // 处理按钮点击
        }
    }

    // 主方法，使用SwingUtilities确保在EDT线程中创建UI
    public static void main(String[] args) {
        SwingUtilities.invokeLater(EnhancedCalculator::new);
    }
}
/*
添加按钮动画 137行
自动补零处理：878行
S:钢琴面板 784行
新增数学计算功能：
开根号 (√)：计算输入数字的平方根，支持正数计算,输入数字后点击 "√" ps:568行
阶乘 (x!)：计算非负整数的阶乘，使用递归算法,输入整数后点击 "x!"  ps:590行
自然对数 (ln)：计算以 e 为底的对数，参数需大于 0,输入正数后点击 "ln"  ps:621行
常用对数 (log)：计算以 10 为底的对数，参数需大于 0,输入正数后点击"log"  ps:643行
正弦函数 (sin)：计算角度的正弦值，自动将角度转换为弧度,输入角度后点击 "sin" ps:665行
余弦函数 (cos)：计算角度的余弦值，自动将角度转换为弧度,输入角度后点击"cos"  ps:684行
正负号切换 (±)：切换当前数字的正负号,点击 "±" 切换当前数字正负 ps:553行
插入常数 (π, e)：快速插入圆周率和自然常数 ps:510行
界面与交互优化
布局调整：将按钮布局改为 6 行 5 列，新增科学计算按钮
模式切换：添加 "MODE" 按钮切换标准 / 科学计算模式 ps:546行
结果格式化：优化计算结果显示，自动去除多余的零 ps:703行
音效控制：
菜单中可开启 / 关闭音效 
音效设置中可调整音量和音调
模式切换：
点击 "MODE" 按钮切换标准 / 科学计算模式（当前仅状态显示，可扩展更多功能）
*/
